module fifo_uart
#(
    parameter   UART_BPS    =   'd50_000_000 ,  
    parameter   CLK_FREQ    =   'd200_000_000
)
(
    input       sys_clk,      
    input       low_clk,      
    input       uart_clk,      
    input       sys_rst_n,    
    input       tx_ready,
    input[2:0]  rd_cnt,
    input[7:0]  wr_data,
    output      tx
);

// 写入控制信号
reg  we;                //synthesis keep; 
reg  [4:0]  we_q;
wire [7:0]  rd_data;    //synthesis keep;
wire [12:0] rdusedw;    //synthesis keep;
wire empty_flag;
reg  [4:0]  tx_ready_q;
       
reg  [15:0] f_wr_cnt;   //synthesis keep;
reg  [15:0] f_rd_cnt;   //synthesis keep;

always @(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n) begin
        tx_ready_q <= 'd0;
    end 
    else begin
        tx_ready_q <= {tx_ready_q[3:0], tx_ready};
    end      
end

always @(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n) begin
        we_q <= 'd0;
    end 
    else begin
        we_q <= {we_q[3:0], we};
    end      
end

always @(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n) begin
        we <= 1'b0;
        f_wr_cnt <= 'd0;
    end
    else if(tx_ready & (rd_cnt < 4) & (f_wr_cnt < 24576)) begin
        we <= 1'b1;
        f_wr_cnt <= f_wr_cnt + 'd1; 
    end
    else begin
        we <= 1'b0;
    end
end

// 读取和发送控制信号
reg re;                 //synthesis keep;
wire done;              //synthesis keep;
reg sending;            // 发送状态标志
reg data_valid;         // 数据有效标志

// 状态定义
parameter IDLE      = 2'b00;
parameter READ_FIFO = 2'b01;
parameter WAIT_SEND = 2'b10;
parameter WAIT_DONE = 2'b11;

reg [1:0] current_state, next_state;

// 状态寄存器
always @(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n) begin
        current_state <= IDLE;
    end
    else begin
        current_state <= next_state;
    end
end

// 下一状态逻辑
always @(*) begin
    next_state = current_state;
    case(current_state)
        IDLE: begin
            if(!empty_flag && f_rd_cnt < f_wr_cnt) begin
                next_state = READ_FIFO;
            end
        end
        
        READ_FIFO: begin
            next_state = WAIT_SEND;
        end
        
        WAIT_SEND: begin
            if(data_valid) begin
                next_state = WAIT_DONE;
        end
        end
        
        WAIT_DONE: begin
            if(done) begin
                if(!empty_flag && f_rd_cnt < f_wr_cnt) begin
                    next_state = READ_FIFO;
                end
                else begin
                    next_state = IDLE;
                end
            end
        end
    endcase
end

// 读取信号延迟链，用于时序控制
reg [1:0] re_q;
always @(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n) begin
        re_q <= 'd0;
    end   
    else begin
        re_q <= {re_q[0], re};
    end
end

// 输出逻辑
always @(posedge sys_clk or negedge sys_rst_n) begin
    if(!sys_rst_n) begin
        re <= 1'b0;
        sending <= 1'b0;
        data_valid <= 1'b0;
        f_rd_cnt <= 'd0;
    end
    else begin
        re <= 1'b0; // 默认不读取
        
        case(current_state)
            READ_FIFO: begin
                re <= 1'b1; // 发起读取
                sending <= 1'b1;
            end
            
            WAIT_SEND: begin
                if(re_q[1]) begin // 读取完成后的下一个周期
                    data_valid <= 1'b1; // 数据有效
                end
            end
            
            WAIT_DONE: begin
                data_valid <= 1'b0; // 发送开始后清除有效标志
                
                if(done) begin
                    sending <= 1'b0;
                    f_rd_cnt <= f_rd_cnt + 1; // 成功发送一个字节
                end
            end
        endcase
    end
end


fifo fifo_inst(
   .clk        (sys_clk   ),
   .rst        (~sys_rst_n),

   .we         (we        ), 
   .di         (wr_data   ), 
   .full_flag  (full_flag ),

   .re         (re        ), 
   .do         (rd_data   ), 
   .empty_flag (empty_flag),
   .rdusedw    (rdusedw   )
);

uart_tx
#(
    .UART_BPS ( UART_BPS ),
    .CLK_FREQ ( CLK_FREQ )
)
uart_tx_inst
(
    .sys_clk  ( sys_clk   ),
    .uart_clk ( uart_clk  ),
    .sys_rst_n( sys_rst_n ),
    .in_data  ( rd_data   ),
    .in_flag  ( tx_flag   ),
    .done     ( done      ),
    .tx       ( tx        )
);

delay_pulse_generator
#(
    .DELAY_WIDTH  ( 4  ),
    .DELAY_CYCLES ( 1  )
)
delay_pulse_generator_inst(
    .low_clk    (low_clk   ),     
    .sys_clk    (sys_clk   ),     
    .sys_rst_n  (sys_rst_n ),       
    .done       (data_valid),        
    .pulse_out  (tx_flag   )    
);

endmodule